<template>
  <div>
    <el-dialog
      v-model="visible"
      title="快照管理"
      class="snapshot-manage-dialog"
    >
      <div class="mx-1 relative">
        <el-button
            type="primary"
            @click="snapshotVisible = true"
            class="snapshot-button"
        >新建快照</el-button>
        <el-table
            class="snapshot-table-scene"
            ref="singleTableRef"
            highlight-current-row
            :data="state.tableData"
            style="width: 100%"
            row-key="ID"
            default-expand-all
            show-overflow-tooltip
        >
          <el-table-column
              align="left"
              property="name"
              label="名称"
          >
            <template v-slot="{ row }">
              <el-icon class="tree-table-vertical" :style="{ 'margin-left': (row.level - 1) * 16 + 'px' }">
                <SvgIcon name="treeTableVertical" size="24"></SvgIcon>
              </el-icon>
              <el-icon class="tree-table-horizontal">
                <SvgIcon name="treeTableHorizontal" size="24"></SvgIcon>
              </el-icon>
              <el-icon class="tree-table" v-if="row.name !== '现在'">
                <SvgIcon name="snapshot" size="24"></SvgIcon>
              </el-icon>
              <el-icon class="tree-table" v-if="row.level !== 0 && row.name === '现在'">
                <SvgIcon name="treeTableCurrent" size="24"></SvgIcon>
              </el-icon>
              <span style=" margin-left: 4px">{{ row.name }}</span>
            </template>
          </el-table-column>
          <el-table-column
              align="center"
              property="cores"
              label="cpu"
              width="80"
          >
            <template v-slot="{ row }">
              <span v-if="baseInfo.cores === row.cores ">{{ row.cores }}</span>
              <span v-if="baseInfo.cores !== row.cores ">
                    {{ row.cores }}
                    <span style="color: #ff0000">（{{ baseInfo.cores }}）</span>
                  </span>
            </template>
          </el-table-column>
          <el-table-column
              align="center"
              property="memory"
              label="内存"
              width="120"
          >
            <template v-slot="{ row }">
              <span v-if="baseInfo.memory === row.memory ">{{ row.memory }}</span>
              <span v-if="baseInfo.memory !== row.memory ">
                    {{ row.memory }}
                    <span style="color: #ff0000">（{{ baseInfo.memory }}）</span>
                  </span>
            </template>
          </el-table-column>
          <el-table-column
              align="center"
              property="isRunning"
              label="状态"
              width="80"
          >
            <template v-slot="{ row }">
              <el-tag
                  :type="row.isRunning? 'success': 'info'"
              >{{
                  row.isRunning ? '运行' : '关闭'
                }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column
              align="center"
              property="description"
              label="简介"
              width="100"
          />
          <el-table-column
              align="center"
              property="CreatedAt"
              label="创建时间"
              width="160"
              :formatter="formatDate"
          />
          <el-table-column
              label="操作"
              align="center"
              :width="120"
              fixed="right"
          >
            <template #default="{ row }">
              <div class="flex items-center justify-center flex-wrap space-x-1" v-if="row.name !== '现在'">
                <el-link class="w-max" type="primary" size="small" :underline="false" @click="revertSnapshot(row)">回滚</el-link>
                <el-link class="w-max" type="danger" size="small" :underline="false" @click="delSnapshot(row)">删除</el-link>
              </div>
            </template>
          </el-table-column>
        </el-table>
        <div class="space-x-1 flex items-center absolute right-0 top-0" />

        <el-dialog v-model="snapshotVisible" title="新建快照" width="560px">
          <el-form
              ref="snapshotFormRef"
              :model="snapshotForm"
              :rules="snapshotRules"
              label-width="100px"
              style="max-width: 460px"
              class="m-auto mt-1"
          >
            <el-form-item label="名称" prop="name">
              <el-input v-model="snapshotForm.name" />
            </el-form-item>
            <el-form-item label="描述" prop="description">
              <el-input type="textarea" v-model="snapshotForm.description" />
            </el-form-item>
          </el-form>
          <template #footer>
        <span>
          <el-button @click="snapshotVisible = false">取 消</el-button>
          <el-button type="primary" @click="addSnapshotData"> 新 建 </el-button>
        </span>
          </template>
        </el-dialog>
      </div>
    </el-dialog>
  </div>
</template>
<script lang="ts" setup>
import {onMounted, onUnmounted, reactive, ref, shallowReactive, watch} from 'vue';
import { emitter } from '@/utils/bus';
import eventBus from 'vue3-eventbus';
import { ElMessage } from 'element-plus/es';
import {
  getSnapshotList,
  delSnapshotApi,
  addSnapshotApi,
  revertSnapshotApi
} from '@/api/topo/vmWare';
import { ElMessageBox } from "element-plus";
import debounce from "lodash/debounce";
import {
  formatObject,
  objectArrayMap,
  dateFormat
} from '@/utils/common';

// 快照表单
const snapshotForm = reactive({
  name: '',
  description: ''
});
const snapshotRules = {
  name: [{ required: true, trigger: 'blur', message: '名称不能为空' }]
};
const snapshotFormRef = ref(null);
const snapshotVisible = ref(false);
const visible = ref(false);

// 快照管理
const tableRef = ref(null);
const state = shallowReactive({
  tableData: [],
});
let baseInfo = [];

let networkData = [];
/**
 * 获取网卡信息
 */
const getNetworkData = (data) =>{
  const tempNetworkArr = JSON.parse(data);
  networkData = [];
  tempNetworkArr.forEach(item =>{
    networkData.push({
      id: item.ID,
      ip: item.ipV4,
      ipAllocationMode: item.ipAllocationMode,
      gateway: item.ipV4Gateway
    });
  })
}

/**
 * 快照管理（防抖）
 * @type {DebouncedFuncLeading<(function(): Promise<void>)|*> | DebouncedFunc<(function(): Promise<void>)|*>}
 */
const getSnapshotData = debounce(async() =>{
  if(visible.value) {
    const { data } = await getSnapshotList(baseInfo.qemuID);
    state.tableData = ( data && data.length > 0 ) ? formatObject(objectArrayMap(data)) : [];
  }
}, import.meta.env.VITE_INPUT_DEBOUNCE_TIME);
emitter.emit('networkData', getNetworkData);

/**
 * 新建快照
 */
const addSnapshotData = () =>{
  snapshotFormRef.value?.validate(async valid => {
    if (valid) {
      addSnapshotApi(baseInfo.qemuID, snapshotForm).then(res => {
        if (!(res instanceof Error)) {
          ElMessage.success('新建成功');
          snapshotVisible.value = false;
        }
      });
    }
  });
}

const revertWarning = ref('');
/**
 * 回滚快照
 * @param arg
 */
const revertSnapshot = (arg) =>{

  // 校验快照（1. 与虚拟机cpu、内存不一致不允许回滚）
  revertWarning.value = '';
  if(baseInfo.cores !== arg.cores || baseInfo.memory !== arg.memory) {
    ElMessage.warning('回滚快照与原虚拟机CPU、内存不一致，不允许回滚！');
    revertWarning.value = arg.id;
    return;
  }

  // 校验快照（1. 判断网卡内容）
  for(let i = 0;i < networkData.length;i++) {
    for(let j = 0;j < arg.networkDetail.length;j++) {
      if(networkData[i].id === arg.networkDetail[j].id) {
        if(networkData[i].ip !== arg.networkDetail[j].ip
            || networkData[i].ipAllocationMode !== arg.networkDetail[j].ipAllocationMode
            || networkData[i].gateway !== arg.networkDetail[j].gateway) {
          ElMessage.warning('回滚快照与原虚拟机网卡信息不一致！');
        }
      }
    }
  }

  revertSnapshotApi(baseInfo.qemuID, arg.id).then(res => {
    if (!(res instanceof Error)) {
      ElMessage.success(res.msg);
    }
  });
}

/**
 * 删除快照
 */
const delSnapshot = (arg) =>{
  ElMessageBox.confirm(
      `删除快照 【${arg.name}】 ，删除后将不可恢复！`,
      '删除快照',
      {
        confirmButtonText: '删 除',
        cancelButtonText: '取 消',
        type: 'warning',
        center: true,
        customClass: 'delMessageBox',
        confirmButtonClass: 'delButtonClass',
      },
  ).then(async () => {
    delSnapshotApi(baseInfo.qemuID, arg.id).then(res => {
      if (!(res instanceof Error)) {
        ElMessage.success(res.msg);
      }
    });
  });
}

const formatDate = (row, column) => {
  return dateFormat(row[column.property]);
};

const topoData = ref({});

/**
 * 处理快照
 */
const snapshotDialogHandle = (cell) =>{

  let tempTopoArr = topoData.value.nodes;
  for(let i = 0;i < tempTopoArr.length;i++) {
    if(cell.id === tempTopoArr[i].id) {
      baseInfo = tempTopoArr[i];
      break;
    }
  }

  visible.value = true;
  getSnapshotData();
}

/**
 * 获取拓扑数据
 * @param data
 */
const getTopoData = (data) =>{
  topoData.value = JSON.parse(data);
}

// 监听弹窗显示、隐藏（隐藏刷新外层列表）
watch(snapshotVisible, cur => {
  snapshotFormRef.value.resetFields();
});

onMounted(() =>{
  emitter.on('updateSnapshotData', getSnapshotData);
  emitter.on('snapshotDialog', snapshotDialogHandle);
  emitter.on('topoData', getTopoData);
})

onUnmounted(() =>{
  emitter.off('updateSnapshotData', getSnapshotData);
  emitter.off('snapshotDialog', snapshotDialogHandle);
  emitter.off('topoData', getTopoData);
})
</script>
<style lang="scss" scoped>
.snapshot-button {
  margin-bottom: 12px;
}

:deep(.snapshot-table-scene) {
  .el-table__expand-icon {
    display: none;
  }

  .el-icon {
    font-size: 20px;
  }


  tr td, tr th {
    height: 42px;
  }

  .el-table__indent {
    display: none;
  }

  .tree-table-vertical {
    top: -7px;
    right: -10px;

    svg {
      width: 20px;
      height: 16px;
      color: #fff;
      fill:currentColor;
    }
  }

  .tree-table-horizontal {
    top: 2px;
    right: 4px;

    svg {
      width: 20px;
      height: 16px;
      color: #fff;
      fill:currentColor;
    }
  }

  .tree-table {
    top: 2px;

    svg {
      width: 16px;
      height: 16px;
      color: #fff;
      fill:currentColor;
    }
  }
}

:deep(.snapshot-manage-dialog) {
  width: 1080px;

  .el-table {
    height: 420px!important;
  }

  .el-table__body-wrapper {
    height: 330px!important;
  }

  .el-empty__image {
    width: 108px!important;
  }
}
</style>
